package com.why.cachecloud.service.custom.alert.impl;

import com.why.cachecloud.dao.AppToUserDao;
import com.why.cachecloud.dao.AppUserDao;
import com.why.cachecloud.dao.WarnLogDao;
import com.why.cachecloud.entity.*;
import com.why.cachecloud.service.alert.WarnConfigService;
import com.why.cachecloud.service.alert.WarnLogService;
import com.why.cachecloud.service.alert.WarnType;
import com.why.cachecloud.service.custom.alert.DingTalkComponent;
import com.why.cachecloud.util.ConstUtils;
import com.why.cachecloud.util.DingDingUtil;
import com.why.cachecloud.web.service.AppService;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections.CollectionUtils;
import org.springframework.core.env.Environment;

import javax.annotation.PostConstruct;
import javax.annotation.Resource;
import java.time.LocalDateTime;
import java.util.*;
import java.util.stream.Collectors;

/**
 * Created by why.developer
 */
@Slf4j
public class DefaultDingTalkComponent implements DingTalkComponent {

    @Resource
    private WarnLogService warnLogService;

    @Resource
    private AppService appService;

    @Resource
    private AppToUserDao appToUserDao;

    @Resource
    private AppUserDao appUserDao;

    @Resource
    private WarnLogDao warnLogDao;

    @Resource
    private WarnConfigService warnConfigService;

    @Resource
    private Environment environment;

    private String bigKeyLinkFormat;

    @PostConstruct
    public void init() {
        String[] activeProfiles = environment.getActiveProfiles();
        if (activeProfiles == null || activeProfiles.length == 0) {
            bigKeyLinkFormat = "http://dev-cachecloud.%s/admin/app/index?appId=%d&tabTag=big_key";
            return;
        }
        List<String> list = Arrays.asList(activeProfiles);
        if (list.contains("qa")) {
            bigKeyLinkFormat = "http://dev-cachecloud.%s/admin/app/index?appId=%d&tabTag=big_key";
            return;
        }
        if (list.contains("prod")) {
            bigKeyLinkFormat = "http://dev-cachecloud.%s/admin/app/index?appId=%d&tabTag=big_key";
            return;
        }
        bigKeyLinkFormat = "http://dev-cachecloud.%s/admin/app/index?appId=%d&tabTag=big_key";
    }

    @Override
    public void sendDingTalk(String message, List<String> phoneList) {
        DingDingUtil.sendMsg(ConstUtils.DING_TALK_ALERT_INTERFACE, ConstUtils.DING_TALK_ACCESS_TOKEN, ConstUtils.DING_TALK_SECRET, message, phoneList);
    }

    @Override
    public void sendDingTalkToAll(String message, List<String> mobileList) {
        DingDingUtil.sendMsg(ConstUtils.DING_TALK_ALERT_INTERFACE, ConstUtils.DING_TALK_ACCESS_TOKEN, ConstUtils.DING_TALK_SECRET, message, mobileList);
    }

    @Override
    public void sendDingTalkToAdmin(String message) {
        DingDingUtil.sendMsg(ConstUtils.DING_TALK_ALERT_INTERFACE, ConstUtils.DING_TALK_ACCESS_TOKEN, ConstUtils.DING_TALK_SECRET, message, ConstUtils.SUPER_MANAGER_MOBILE);
    }

    @Override
    public void sendDingTalk(WarnConfig warnConfig, long appId, String msg) {
        Integer alertTime = warnConfig.getAlertTime();
        Integer alertCount = warnConfig.getAlertCount();

        LocalDateTime dateTime = LocalDateTime.now().plusMinutes(Math.negateExact(alertTime));

        int dbRecord = warnLogService.countBy(appId, warnConfig.getWarnType(), dateTime);
        if (dbRecord >= alertCount) {
            log.warn("告警频率超过指定次数被拦截,类型:{},配置告警频率为:{}分{}次,当前已告警次数:{}", warnConfig.getWarnType(), warnConfig.getAlertTime(), warnConfig.getAlertCount(), dbRecord);
            return;
        }

        List<AppUser> appUsers = null;
        Integer alertType = warnConfig.getAlertType();
        if (alertType == 1) {
            appUsers = getAppAdminList(appId);
        } else if (alertType == 5) {
            appUsers = getSysAdminList();
        } else if (alertType == 9) {
            List<AppUser> adminList = getAppAdminList(appId);
            List<AppUser> sysAdminList = getSysAdminList();
            adminList.addAll(sysAdminList);
            appUsers = adminList;
        }

        Set<AppUser> appUserSet = appUsers.stream().filter(au -> au.getIsAlert() == 1).collect(Collectors.toSet());
        if (appUserSet.isEmpty()) {
            return;
        }

        String ids = appUserSet.stream().map(AppUser::getId).map(String::valueOf).collect(Collectors.joining(","));

        WarnLog warnLog = new WarnLog()
                .setWarnType(warnConfig.getWarnType())
                .setAppId(appId)
                .setUserIds(ids)
                .setContent(msg)
                .setFlag(0)
                .setCreateTime(LocalDateTime.now());

        warnLogDao.insert(warnLog);

        List<String> mobileList = appUserSet.stream().map(AppUser::getMobile).map(String::valueOf).collect(Collectors.toList());
        if (!msg.contains("@")) {
            for (String mb : mobileList) {
                msg += "@" + mb;
            }
        }

        DingDingUtil.sendMsg(ConstUtils.DING_TALK_ALERT_INTERFACE, ConstUtils.DING_TALK_ACCESS_TOKEN, ConstUtils.DING_TALK_SECRET, msg, mobileList);
    }

    @Override
    public void sendDingTalk(WarnType warnType, Collection<AppDesc> appDescs) {
        if (warnType == null || CollectionUtils.isEmpty(appDescs)) {
            return;
        }
        WarnConfig warnConfig = warnConfigService.queryConfig(0, WarnType.bigKey);
        if (warnConfig == null) {
            return;
        }
        sendDingTalk(warnConfig, appDescs);
    }

    @Override
    public void sendDingTalk(WarnConfig warnConfig, Collection<AppDesc> appDescs) {
        if (warnConfig == null || CollectionUtils.isEmpty(appDescs)) {
            return;
        }
        Integer alertCount = warnConfig.getAlertCount();
        if (alertCount == 0) {
            return;
        }
        Integer alertTime = warnConfig.getAlertTime();

        LocalDateTime dateTime = LocalDateTime.now().plusMinutes(Math.negateExact(alertTime));

        int dbRecord = warnLogService.countBy(0, warnConfig.getWarnType(), dateTime);
        if (dbRecord >= alertCount) {
            return;
        }

        Set<String> mobileList = new HashSet<>();
        Set<Long> userId = new HashSet<>();
        for (AppDesc appDesc : appDescs) {
            List<AppUser> appAdminList = getAppAdminList(appDesc.getAppId());
            List<String> mobileListTmp = appAdminList.stream().map(AppUser::getMobile).collect(Collectors.toList());
            mobileList.addAll(mobileListTmp);
            List<Long> collect = appAdminList.stream().map(AppUser::getId).collect(Collectors.toList());
            userId.addAll(collect);
        }

        String message = buildMessage(warnConfig, appDescs);

        WarnLog warnLog = new WarnLog()
                .setWarnType(warnConfig.getWarnType())
                .setAppId(0L)
                .setUserIds(Arrays.toString(userId.toArray(new Long[]{})))
                .setContent(message)
                .setFlag(0)
                .setCreateTime(LocalDateTime.now());

        warnLogDao.insert(warnLog);

        DingDingUtil.sendMsg(ConstUtils.DING_TALK_ALERT_INTERFACE, ConstUtils.DING_TALK_ACCESS_TOKEN, ConstUtils.DING_TALK_SECRET, message, new ArrayList<>(mobileList));
    }

    private String buildMessage(WarnConfig warnConfig, Collection<AppDesc> appDescs) {
        if (warnConfig.getWarnType().equals(WarnType.bigKey.name())) {
            StringBuilder sb = new StringBuilder("下列应用检测有大key,请及时关注检查!!!\r\n");
            for (AppDesc appDesc : appDescs) {
                List<AppUser> appAdminList = getAppAdminList(appDesc.getAppId());
                // [天气](https://www.dingtalk.com)
                sb.append(buildAppLink(appDesc)).append(" ");
                appAdminList.forEach(aa -> sb.append("@").append(aa.getMobile()).append(" "));
                sb.append("\r\n");
            }
            return sb.toString();
        }
        return "---";
    }

    private String buildAppLink(AppDesc appDesc) {
        String link = String.format(bigKeyLinkFormat, ConstUtils.COOKIE_DOMAIN, appDesc.getAppId());

        //[天气](https://www.dingtalk.com)
        return "[" + appDesc.getName() + "](" + link + ")";
    }

    private List<AppUser> getAppAdminList(long appId) {
        List<AppToUser> appToUsers = appToUserDao.getByAppId(appId);
        return appToUsers.stream().map(AppToUser::getUserId).map(appUserDao::get).collect(Collectors.toList());
    }

    private List<AppUser> getSysAdminList() {
        return appUserDao.getAdminList();
    }

}